# ifndef __Dialog_H_
# define __Dialog_H_

class CTabSheet;
class CDialog;

class CDialogBase {
	// Disable copy semantics.
	CDialogBase (const CDialogBase &);
	void operator = (const CDialogBase &);

  public:
	CDialogBase (WORD _wResID, bool _bHandleURLs = false) :
		m_wResID (_wResID),
		m_hWnd (NULL),
		m_bHandleURLs (_bHandleURLs)
	{}
	virtual ~CDialogBase () {}

	operator HWND () const {return m_hWnd;}

	virtual INT_PTR OnMessage (UINT _uMsg, WPARAM _wParam, LPARAM _lParam);

	// NOTE: return false to set focus explicitly.
	virtual bool OnInit (HWND _hwndFocus) {return true;}
	virtual void OnClose () {}
	virtual void OnDestroy () {}
	virtual	void OnPaint (const PAINTSTRUCT & _ps) {}
	virtual void OnCommand (WORD _wCmd, WORD _wNotifyCode, HWND _hwndCtl) {}
	// NOTE: to return a value, please use SetMsgResult() and return 'true'.
	virtual bool OnNotify (int _idCtrl, NMHDR * _pInfo) {return false;}
	virtual void OnSize (DWORD _dwResizeFlag, WORD _wWidth,	WORD _wHeight) {}
	virtual void OnMove (int _x, int _y) {}
	virtual void OnHScroll (WORD _wRequest, WORD _wPos, HWND _hwndCtl) {}
	virtual void OnVScroll (WORD _wRequest, WORD _wPos, HWND _hwndCtl) {}

	void SetMsgResult (LONG _lMsgResult);

  protected:
	friend class CTabSheet;
	friend class CDialog;

	const WORD m_wResID;
	HWND m_hWnd;
	const bool m_bHandleURLs;

	HWND GetDlgItem          (UINT _uiID) const;
	void GetDlgItemRect      (UINT _uiID, RECT & _rect) const;
	void SetFocus            (UINT _uiID);
	void EnableDlgItem       (UINT _uiID, bool _bEnable);
	void ShowDlgItem         (UINT _uiID, bool _bShow);
	void GetDlgItemText      (UINT _uiID, TCHAR * _strText, size_t _cSize) const;
	void GetDlgItemText      (UINT _uiID, string_t & _str) const;
	size_t GetDlgItemTextLen (UINT _uiID) const;
	void SetDlgItemText      (UINT _uiID, const TCHAR * _strText);
	void SetDlgItemTextF     (UINT _uiID, const TCHAR * _strFormat, ...);
	void SetDlgItemUInt      (UINT _uiID, UINT _uiValue);
	UINT GetDlgItemUInt      (UINT _uiID) const;
	void CheckDlgButton      (UINT _uiID, bool _bCheck);
	void CheckRadioButton    (UINT _uiID, const UINT * _pButtons, size_t _cButtons);
	bool IsDlgButtonChecked  (UINT _uiID) const;

	void SendOK ();
	void SendCommand (WPARAM _wParam);
	void PostCommand (WPARAM _wParam);
};

class CDialog : public CDialogBase {
  public:
	CDialog (WORD _wResID, bool _bHandleURLs);
	CDialog (WORD _wResID);
	~CDialog ();

	INT_PTR ShowModal    (HWND _hWndParent);

	bool CreateModeless (HWND _hWndParent);
	void Show ();
	void Hide ();

	// Override.
	virtual void OnCommand (WORD _wCmd, WORD _wNotifyCode, HWND _hwndCtl);

	static bool IsDialogMessage (MSG * _pMsg);

  protected:
	void EndDialog (INT_PTR _nResult);

  private:
	static INT_PTR CALLBACK _DlgProc (HWND _hWnd, UINT _uMsg, WPARAM _wParam, LPARAM _lParam);

	static std::vector<HWND> s_vecModelessDlgs;
	void _AddModelessToList ();
	void _RemoveModelessFromList ();
};

template<typename _D>
void ShowModeless (_D * & _pD, HWND _hwndParent) {
	if (! _pD) {
		_pD = new _D;
		_pD->CreateModeless (_hwndParent);
		_pD->Show ();
	} else {
		_pD->Show ();
		::SetFocus (* _pD);
	}
}

# endif // __Dialog_H_
